package thread;

import java.util.concurrent.locks.StampedLock;

/**
 * \* User: Administrator
 * <p>
 * \* Date: 2020/11/17
 * <p>
 * \* Time: 15:00
 * <p>
 * \* Description:
 * \
 */
public class StampedLockDemo {

    private static double x, y;
    private static final StampedLock sl = new StampedLock();

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5000; i++) {
            new Thread(()->{
//                move(1 , 2);
                distanceFromOrigin();
            }).start();
        }

        Thread.sleep(3000);
        System.out.println(x);
        System.out.println(y);
    }

    static void move(double deltaX, double deltaY) { // an exclusively locked method
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
            System.out.println("move执行===");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            sl.unlockWrite(stamp);
        }
//        x += deltaX;
//        y += deltaY;
    }

    static double distanceFromOrigin() { // A read-only method
        long stamp = sl.tryOptimisticRead();
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) {
            stamp = sl.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }

    void moveIfAtOrigin(double newX, double newY) { // upgrade
        // Could instead start with optimistic, not read mode
        long stamp = sl.readLock();
        try {
            while (x == 0.0 && y == 0.0) {
                long ws = sl.tryConvertToWriteLock(stamp);
                if (ws != 0L) {
                    stamp = ws;
                    x = newX;
                    y = newY;
                    break;
                } else {
                    sl.unlockRead(stamp);
                    stamp = sl.writeLock();
                }
            }
        } finally {
            sl.unlock(stamp);
        }
    }
}
